package test;

import dao.UserDao;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringConfigTest_Bean {
    /**
     * 1）ClassPathXmlApplicationContext
     *       它是从类的根路径下加载配置文件,在maven项目中是resource目录 推荐使用这种
     * 2）FileSystemXmlApplicationContext
     *       它是从磁盘路径上加载配置文件，配置文件可以在磁盘的任意位置。
     * 3）AnnotationConfigApplicationContext
     *       当使用注解配置容器对象时，需要使用此类来创建 spring 容器。它用来读取注解。
     */
    ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

    /**
     * Spring快速入门
     */
    @Test
    public void testSave() {
        UserDao userDao = (UserDao) app.getBean("userDao",UserDao.class);
        userDao.save();
    }

    /**
     * 测试scope属性
     * Bean标签范围配置
     * 1）当scope的取值为singleton时
     * Bean的实例化个数：1个
     * Bean的实例化时机：当Spring核心文件被加载时，实例化配置的Bean实例
     * Bean的生命周期：
     * 对象创建：当应用加载，创建容器时，对象就被创建了
     * 对象运行：只要容器在，对象一直活着
     * 对象销毁：当应用卸载，销毁容器时，对象就被销毁了
     * 2）当scope的取值为prototype时
     * Bean的实例化个数：多个
     * Bean的实例化时机：当调用getBean()方法时实例化Bean
     * 对象创建：当使用对象时，创建新的对象实例
     * 对象运行：只要对象在使用中，就一直活着
     * 对象销毁：当对象长时间不用时，被 Java 的垃圾回收器回收了
     */
    @Test
    public void testScope() {
        UserDao userDao1 = (UserDao) app.getBean("userDao");
        UserDao userDao2 = (UserDao) app.getBean("userDao");
        //当scope为prototype时，会创建不同的对象。
        //当scope为singleton(默认)时，会创建相同的对象。
        System.out.println("userDao1 = " + userDao1);//userDao1 = dao.impl.UserDaoImpl@1563da5
        System.out.println("userDao2 = " + userDao2);//userDao2 = dao.impl.UserDaoImpl@1563da5
    }

    /**
     * 测试初始化和销毁
     * Bean标签生命周期配置
     * init-method：指定类中的初始化方法名称
     * destroy-method：指定类中销毁方法名称
     */
    @Test
    public void testInitAndDestroy() {
        //创建对象，会运行初始化方法并创建bean对象
        UserDao userDao = (UserDao) app.getBean("userDao");
        //输出对象地址
        System.out.println("userDao = " + userDao);
        //销毁Spring容器，会运行销毁方法
        app.close();
    }

    /**
     * Spring工厂静态方法创建Bean对象
     * 需要在bean标签中配置factory-method属性
     * Spring解析到factory-method属性后会找到对应的工厂类执行指定的方法返回对象
     */
    @Test
    public void testStaticFactory() {
        UserDao userDao = (UserDao) app.getBean("userDaoByStatic");
        System.out.println("工厂静态方法创建的userDao = " + userDao);
    }

    /**
     * Spring工厂非静态方法创建Bean对象
     * 需要先创建工厂对象，再通过工厂对象调用工厂类中的方法
     * 通过属性factory-bean:指定工厂对象，factory-method:执行工厂中指定的方法返回对象
     */
    @Test
    public void testDynamicFactory() {
        UserDao userDao = (UserDao) app.getBean("userDaoByDynamic",UserDao.class);
        System.out.println("工厂非静态方法创建的userDao = " + userDao);
    }


}
